/**
 * 性能监控和报告脚本
 * Performance Monitoring and Reporting Script
 */

const fs = require('fs').promises;
const path = require('path');
const { exec } = require('child_process');
const { promisify } = require('util');
const mysql = require('mysql2/promise');

const execAsync = promisify(exec);

// 加载配置
require('dotenv').config({ path: path.join(__dirname, '../.env') });

const config = {
  project: {
    name: 'personal-cloud-notes',
    dir: process.env.PROJECT_DIR || '/var/www/personal-cloud-notes'
  },
  database: {
    host: process.env.DB_HOST || 'localhost',
    port: process.env.DB_PORT || 3306,
    user: process.env.DB_USER || 'notes_user',
    password: process.env.DB_PASSWORD,
    database: process.env.DB_NAME || 'personal_cloud_notes'
  },
  monitoring: {
    interval: parseInt(process.env.METRICS_INTERVAL) || 30000,
    reportPath: process.env.LOG_PATH || '/var/www/personal-cloud-notes/data/reports',
    logPath: process.env.LOG_PATH || '/var/www/personal-cloud-notes/data/logs'
  },
  thresholds: {
    cpu: 80,
    memory: 85,
    responseTime: 5000,
    diskUsage: 90,
    dbConnections: 80
  }
};

// 颜色定义
const colors = {
  reset: '\x1b[0m',
  red: '\x1b[31m',
  green: '\x1b[32m',
  yellow: '\x1b[33m',
  blue: '\x1b[34m',
  purple: '\x1b[35m',
  cyan: '\x1b[36m'
};

/**
 * 打印带颜色的消息
 */
function printMessage(color, message) {
  console.log(`${color}${message}${colors.reset}`);
}

/**
 * 记录性能数据到文件
 */
async function logPerformanceData(data) {
  const logFile = path.join(config.monitoring.logPath, 'performance.log');
  const timestamp = new Date().toISOString();
  const logEntry = `${timestamp} - ${JSON.stringify(data)}\n`;
  
  try {
    await fs.appendFile(logFile, logEntry);
  } catch (error) {
    console.error('写入性能日志失败:', error.message);
  }
}

/**
 * 获取系统CPU使用率
 */
async function getCpuUsage() {
  try {
    // 使用top命令获取CPU使用率
    const { stdout } = await execAsync("top -bn1 | grep 'Cpu(s)' | awk '{print $2}' | sed 's/%us,//'");
    let cpuUsage = parseFloat(stdout.trim());
    
    // 如果获取失败，尝试使用vmstat
    if (isNaN(cpuUsage)) {
      const { stdout: vmstatOutput } = await execAsync("vmstat 1 2 | tail -1 | awk '{print 100-$15}'");
      cpuUsage = parseFloat(vmstatOutput.trim());
    }
    
    return isNaN(cpuUsage) ? 0 : cpuUsage;
  } catch (error) {
    console.error('获取CPU使用率失败:', error.message);
    return 0;
  }
}

/**
 * 获取内存使用情况
 */
async function getMemoryUsage() {
  try {
    const { stdout } = await execAsync("free -m | awk 'NR==2{printf \"%s %s %s\", $3*100/$2, $3, $2}'");
    const [usagePercent, usedMB, totalMB] = stdout.trim().split(' ').map(Number);
    
    return {
      usagePercent: Math.round(usagePercent),
      usedMB,
      totalMB,
      availableMB: totalMB - usedMB
    };
  } catch (error) {
    console.error('获取内存使用情况失败:', error.message);
    return { usagePercent: 0, usedMB: 0, totalMB: 0, availableMB: 0 };
  }
}

/**
 * 获取磁盘使用情况
 */
async function getDiskUsage() {
  try {
    const { stdout } = await execAsync("df / | awk 'NR==2{printf \"%s %s %s\", $5, $4, $2}'");
    const [usageStr, availableKB, totalKB] = stdout.trim().split(' ');
    const usagePercent = parseInt(usageStr.replace('%', ''));
    const availableGB = Math.round(parseInt(availableKB) / 1024 / 1024);
    const totalGB = Math.round(parseInt(totalKB) / 1024 / 1024);
    
    return {
      usagePercent,
      availableGB,
      totalGB,
      usedGB: totalGB - availableGB
    };
  } catch (error) {
    console.error('获取磁盘使用情况失败:', error.message);
    return { usagePercent: 0, availableGB: 0, totalGB: 0, usedGB: 0 };
  }
}

/**
 * 获取系统负载
 */
async function getSystemLoad() {
  try {
    const { stdout } = await execAsync("uptime | awk -F'load average:' '{print $2}' | awk '{print $1}' | sed 's/,//'");
    const loadAvg = parseFloat(stdout.trim());
    
    const { stdout: coresOutput } = await execAsync("nproc");
    const cores = parseInt(coresOutput.trim());
    
    const loadPercent = Math.round((loadAvg / cores) * 100);
    
    return {
      loadAvg,
      cores,
      loadPercent
    };
  } catch (error) {
    console.error('获取系统负载失败:', error.message);
    return { loadAvg: 0, cores: 1, loadPercent: 0 };
  }
}

/**
 * 获取网络统计信息
 */
async function getNetworkStats() {
  try {
    // 获取网络接口统计
    const { stdout } = await execAsync("cat /proc/net/dev | grep -E '(eth|ens|enp)' | head -1 | awk '{print $2, $10}'");
    const [rxBytes, txBytes] = stdout.trim().split(' ').map(Number);
    
    // 获取网络连接数
    const { stdout: connectionsOutput } = await execAsync("netstat -an | grep ESTABLISHED | wc -l");
    const connections = parseInt(connectionsOutput.trim());
    
    return {
      rxBytes: rxBytes || 0,
      txBytes: txBytes || 0,
      connections
    };
  } catch (error) {
    console.error('获取网络统计失败:', error.message);
    return { rxBytes: 0, txBytes: 0, connections: 0 };
  }
}

/**
 * 获取数据库性能指标
 */
async function getDatabaseMetrics() {
  let connection;
  try {
    connection = await mysql.createConnection({
      host: config.database.host,
      port: config.database.port,
      user: config.database.user,
      password: config.database.password,
      database: config.database.database
    });
    
    // 获取数据库状态
    const [statusRows] = await connection.execute('SHOW STATUS');
    const status = {};
    statusRows.forEach(row => {
      status[row.Variable_name] = row.Value;
    });
    
    // 获取数据库大小
    const [sizeRows] = await connection.execute(`
      SELECT 
        ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS size_mb
      FROM information_schema.tables 
      WHERE table_schema = ?
    `, [config.database.database]);
    
    // 获取表统计信息
    const [tableRows] = await connection.execute(`
      SELECT 
        table_name,
        table_rows,
        ROUND((data_length + index_length) / 1024 / 1024, 2) AS size_mb
      FROM information_schema.tables 
      WHERE table_schema = ?
      ORDER BY (data_length + index_length) DESC
    `, [config.database.database]);
    
    return {
      connections: parseInt(status.Threads_connected) || 0,
      maxConnections: parseInt(status.max_connections) || 0,
      queries: parseInt(status.Queries) || 0,
      slowQueries: parseInt(status.Slow_queries) || 0,
      uptime: parseInt(status.Uptime) || 0,
      databaseSizeMB: sizeRows[0]?.size_mb || 0,
      tables: tableRows.map(row => ({
        name: row.table_name,
        rows: row.table_rows,
        sizeMB: row.size_mb
      }))
    };
  } catch (error) {
    console.error('获取数据库指标失败:', error.message);
    return {
      connections: 0,
      maxConnections: 0,
      queries: 0,
      slowQueries: 0,
      uptime: 0,
      databaseSizeMB: 0,
      tables: []
    };
  } finally {
    if (connection) {
      await connection.end();
    }
  }
}

/**
 * 获取应用性能指标
 */
async function getApplicationMetrics() {
  try {
    // 获取PM2进程信息
    const { stdout: pm2Output } = await execAsync('sudo -u pm2 pm2 jlist');
    const pm2Processes = JSON.parse(pm2Output);
    
    const appProcess = pm2Processes.find(p => p.name === config.project.name);
    
    if (!appProcess) {
      return {
        status: 'offline',
        cpu: 0,
        memory: 0,
        restarts: 0,
        uptime: 0
      };
    }
    
    return {
      status: appProcess.pm2_env.status,
      cpu: appProcess.monit.cpu,
      memory: Math.round(appProcess.monit.memory / 1024 / 1024), // MB
      restarts: appProcess.pm2_env.restart_time,
      uptime: Date.now() - appProcess.pm2_env.pm_uptime
    };
  } catch (error) {
    console.error('获取应用指标失败:', error.message);
    return {
      status: 'unknown',
      cpu: 0,
      memory: 0,
      restarts: 0,
      uptime: 0
    };
  }
}

/**
 * 测试HTTP响应时间
 */
async function getHttpResponseTime() {
  const testUrls = [
    'http://localhost:3000',
    'http://localhost:3000/api/health',
    'http://localhost'
  ];
  
  const results = [];
  
  for (const url of testUrls) {
    try {
      const startTime = Date.now();
      const { stdout } = await execAsync(`curl -s -o /dev/null -w "%{http_code}" --connect-timeout 10 --max-time 10 "${url}"`);
      const endTime = Date.now();
      
      const responseTime = endTime - startTime;
      const statusCode = parseInt(stdout.trim());
      
      results.push({
        url,
        responseTime,
        statusCode,
        success: statusCode >= 200 && statusCode < 400
      });
    } catch (error) {
      results.push({
        url,
        responseTime: -1,
        statusCode: 0,
        success: false,
        error: error.message
      });
    }
  }
  
  return results;
}

/**
 * 获取日志统计信息
 */
async function getLogStats() {
  try {
    const logDir = config.monitoring.logPath;
    const stats = {
      totalSize: 0,
      files: [],
      errors: 0,
      warnings: 0
    };
    
    // 获取日志文件信息
    const files = await fs.readdir(logDir);
    
    for (const file of files) {
      if (file.endsWith('.log')) {
        const filePath = path.join(logDir, file);
        const fileStat = await fs.stat(filePath);
        
        stats.totalSize += fileStat.size;
        stats.files.push({
          name: file,
          size: fileStat.size,
          modified: fileStat.mtime
        });
        
        // 统计错误和警告（仅检查最近的日志）
        if (fileStat.mtime > Date.now() - 24 * 60 * 60 * 1000) {
          try {
            const content = await fs.readFile(filePath, 'utf8');
            const lines = content.split('\n');
            
            for (const line of lines) {
              if (line.toLowerCase().includes('error')) {
                stats.errors++;
              } else if (line.toLowerCase().includes('warning') || line.toLowerCase().includes('warn')) {
                stats.warnings++;
              }
            }
          } catch (error) {
            // 忽略读取错误
          }
        }
      }
    }
    
    return stats;
  } catch (error) {
    console.error('获取日志统计失败:', error.message);
    return {
      totalSize: 0,
      files: [],
      errors: 0,
      warnings: 0
    };
  }
}

/**
 * 收集所有性能指标
 */
async function collectMetrics() {
  printMessage(colors.blue, '收集性能指标...');
  
  const metrics = {
    timestamp: new Date().toISOString(),
    system: {
      cpu: await getCpuUsage(),
      memory: await getMemoryUsage(),
      disk: await getDiskUsage(),
      load: await getSystemLoad(),
      network: await getNetworkStats()
    },
    database: await getDatabaseMetrics(),
    application: await getApplicationMetrics(),
    http: await getHttpResponseTime(),
    logs: await getLogStats()
  };
  
  return metrics;
}

/**
 * 分析性能数据并生成警报
 */
function analyzeMetrics(metrics) {
  const alerts = [];
  
  // CPU使用率检查
  if (metrics.system.cpu > config.thresholds.cpu) {
    alerts.push({
      level: 'WARNING',
      type: 'CPU',
      message: `CPU使用率过高: ${metrics.system.cpu}%`,
      value: metrics.system.cpu,
      threshold: config.thresholds.cpu
    });
  }
  
  // 内存使用率检查
  if (metrics.system.memory.usagePercent > config.thresholds.memory) {
    alerts.push({
      level: 'WARNING',
      type: 'MEMORY',
      message: `内存使用率过高: ${metrics.system.memory.usagePercent}%`,
      value: metrics.system.memory.usagePercent,
      threshold: config.thresholds.memory
    });
  }
  
  // 磁盘使用率检查
  if (metrics.system.disk.usagePercent > config.thresholds.diskUsage) {
    alerts.push({
      level: 'CRITICAL',
      type: 'DISK',
      message: `磁盘使用率过高: ${metrics.system.disk.usagePercent}%`,
      value: metrics.system.disk.usagePercent,
      threshold: config.thresholds.diskUsage
    });
  }
  
  // HTTP响应时间检查
  const slowResponses = metrics.http.filter(r => r.responseTime > config.thresholds.responseTime);
  if (slowResponses.length > 0) {
    alerts.push({
      level: 'WARNING',
      type: 'HTTP_RESPONSE',
      message: `HTTP响应时间过长: ${slowResponses.map(r => `${r.url}(${r.responseTime}ms)`).join(', ')}`,
      value: slowResponses.map(r => r.responseTime),
      threshold: config.thresholds.responseTime
    });
  }
  
  // 数据库连接数检查
  if (metrics.database.maxConnections > 0) {
    const connectionUsage = (metrics.database.connections / metrics.database.maxConnections) * 100;
    if (connectionUsage > config.thresholds.dbConnections) {
      alerts.push({
        level: 'WARNING',
        type: 'DATABASE_CONNECTIONS',
        message: `数据库连接使用率过高: ${Math.round(connectionUsage)}%`,
        value: connectionUsage,
        threshold: config.thresholds.dbConnections
      });
    }
  }
  
  // 应用状态检查
  if (metrics.application.status !== 'online') {
    alerts.push({
      level: 'CRITICAL',
      type: 'APPLICATION_STATUS',
      message: `应用状态异常: ${metrics.application.status}`,
      value: metrics.application.status,
      threshold: 'online'
    });
  }
  
  return alerts;
}

/**
 * 生成性能报告
 */
async function generatePerformanceReport(metrics, alerts) {
  const reportDir = config.monitoring.reportPath;
  await fs.mkdir(reportDir, { recursive: true });
  
  const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
  const reportFile = path.join(reportDir, `performance-report-${timestamp}.json`);
  
  const report = {
    metadata: {
      generatedAt: new Date().toISOString(),
      version: '1.0.0',
      service: config.project.name
    },
    summary: {
      status: alerts.length === 0 ? 'healthy' : alerts.some(a => a.level === 'CRITICAL') ? 'critical' : 'warning',
      totalAlerts: alerts.length,
      criticalAlerts: alerts.filter(a => a.level === 'CRITICAL').length,
      warningAlerts: alerts.filter(a => a.level === 'WARNING').length
    },
    metrics,
    alerts,
    recommendations: generateRecommendations(metrics, alerts)
  };
  
  await fs.writeFile(reportFile, JSON.stringify(report, null, 2));
  
  printMessage(colors.green, `性能报告已生成: ${reportFile}`);
  return reportFile;
}

/**
 * 生成优化建议
 */
function generateRecommendations(metrics, alerts) {
  const recommendations = [];
  
  // 基于警报生成建议
  for (const alert of alerts) {
    switch (alert.type) {
      case 'CPU':
        recommendations.push({
          type: 'OPTIMIZATION',
          priority: 'HIGH',
          message: '考虑优化应用代码或增加服务器资源',
          action: '检查CPU密集型操作，考虑使用缓存或异步处理'
        });
        break;
      
      case 'MEMORY':
        recommendations.push({
          type: 'OPTIMIZATION',
          priority: 'HIGH',
          message: '检查内存泄漏或考虑增加内存',
          action: '分析内存使用模式，优化数据结构和缓存策略'
        });
        break;
      
      case 'DISK':
        recommendations.push({
          type: 'MAINTENANCE',
          priority: 'CRITICAL',
          message: '立即清理磁盘空间',
          action: '清理日志文件、临时文件和旧备份'
        });
        break;
      
      case 'HTTP_RESPONSE':
        recommendations.push({
          type: 'OPTIMIZATION',
          priority: 'MEDIUM',
          message: '优化应用响应时间',
          action: '检查数据库查询、网络延迟和代码性能'
        });
        break;
      
      case 'DATABASE_CONNECTIONS':
        recommendations.push({
          type: 'CONFIGURATION',
          priority: 'HIGH',
          message: '优化数据库连接池配置',
          action: '检查连接泄漏，调整连接池大小'
        });
        break;
    }
  }
  
  // 基于指标生成一般性建议
  if (metrics.logs.errors > 10) {
    recommendations.push({
      type: 'MONITORING',
      priority: 'MEDIUM',
      message: '错误日志数量较多，需要关注',
      action: '分析错误日志，修复潜在问题'
    });
  }
  
  if (metrics.database.slowQueries > 0) {
    recommendations.push({
      type: 'OPTIMIZATION',
      priority: 'MEDIUM',
      message: '存在慢查询，影响性能',
      action: '优化数据库查询，添加必要的索引'
    });
  }
  
  return recommendations;
}

/**
 * 显示实时监控
 */
async function showRealTimeMonitoring(interval = 5000) {
  printMessage(colors.cyan, '开始实时性能监控...');
  printMessage(colors.blue, `监控间隔: ${interval/1000}秒`);
  printMessage(colors.yellow, '按 Ctrl+C 停止监控');
  
  while (true) {
    try {
      console.clear();
      printMessage(colors.cyan, '=== 个人云笔记性能监控 ===');
      printMessage(colors.blue, `更新时间: ${new Date().toLocaleString()}`);
      console.log();
      
      const metrics = await collectMetrics();
      const alerts = analyzeMetrics(metrics);
      
      // 显示系统指标
      printMessage(colors.yellow, '系统资源:');
      console.log(`  CPU: ${metrics.system.cpu.toFixed(1)}%`);
      console.log(`  内存: ${metrics.system.memory.usagePercent}% (${metrics.system.memory.usedMB}MB/${metrics.system.memory.totalMB}MB)`);
      console.log(`  磁盘: ${metrics.system.disk.usagePercent}% (${metrics.system.disk.usedGB}GB/${metrics.system.disk.totalGB}GB)`);
      console.log(`  负载: ${metrics.system.load.loadAvg} (${metrics.system.load.loadPercent}%)`);
      console.log();
      
      // 显示应用指标
      printMessage(colors.yellow, '应用状态:');
      console.log(`  状态: ${metrics.application.status}`);
      console.log(`  CPU: ${metrics.application.cpu}%`);
      console.log(`  内存: ${metrics.application.memory}MB`);
      console.log(`  重启次数: ${metrics.application.restarts}`);
      console.log();
      
      // 显示数据库指标
      printMessage(colors.yellow, '数据库:');
      console.log(`  连接数: ${metrics.database.connections}/${metrics.database.maxConnections}`);
      console.log(`  数据库大小: ${metrics.database.databaseSizeMB}MB`);
      console.log(`  慢查询: ${metrics.database.slowQueries}`);
      console.log();
      
      // 显示HTTP响应
      printMessage(colors.yellow, 'HTTP响应:');
      metrics.http.forEach(result => {
        const status = result.success ? '✓' : '✗';
        const color = result.success ? colors.green : colors.red;
        console.log(`  ${status} ${result.url}: ${result.responseTime}ms (${result.statusCode})`);
      });
      console.log();
      
      // 显示警报
      if (alerts.length > 0) {
        printMessage(colors.red, '⚠️  活动警报:');
        alerts.forEach(alert => {
          const color = alert.level === 'CRITICAL' ? colors.red : colors.yellow;
          printMessage(color, `  [${alert.level}] ${alert.message}`);
        });
      } else {
        printMessage(colors.green, '✓ 系统运行正常，无警报');
      }
      
      await new Promise(resolve => setTimeout(resolve, interval));
    } catch (error) {
      console.error('监控过程中发生错误:', error.message);
      await new Promise(resolve => setTimeout(resolve, interval));
    }
  }
}

/**
 * 显示帮助信息
 */
function showHelp() {
  console.log('个人云笔记性能监控脚本 v1.0.0');
  console.log();
  console.log('用法: node performance-monitor.js [选项]');
  console.log();
  console.log('选项:');
  console.log('  --help, -h           显示帮助信息');
  console.log('  --collect            收集一次性能指标');
  console.log('  --report             生成性能报告');
  console.log('  --monitor            实时监控模式');
  console.log('  --interval SECONDS   监控间隔（默认5秒）');
  console.log('  --daemon             守护进程模式');
  console.log();
  console.log('示例:');
  console.log('  node performance-monitor.js --collect     # 收集一次指标');
  console.log('  node performance-monitor.js --report      # 生成报告');
  console.log('  node performance-monitor.js --monitor     # 实时监控');
  console.log('  node performance-monitor.js --daemon      # 后台运行');
  console.log();
}

/**
 * 主函数
 */
async function main() {
  const args = process.argv.slice(2);
  
  // 处理命令行参数
  if (args.includes('--help') || args.includes('-h')) {
    showHelp();
    return;
  }
  
  const collectOnly = args.includes('--collect');
  const generateReport = args.includes('--report');
  const monitorMode = args.includes('--monitor');
  const daemonMode = args.includes('--daemon');
  
  const intervalIndex = args.indexOf('--interval');
  const interval = intervalIndex !== -1 && args[intervalIndex + 1] 
    ? parseInt(args[intervalIndex + 1]) * 1000 
    : 5000;
  
  try {
    if (monitorMode) {
      await showRealTimeMonitoring(interval);
    } else if (daemonMode) {
      printMessage(colors.blue, '启动守护进程模式...');
      
      while (true) {
        const metrics = await collectMetrics();
        const alerts = analyzeMetrics(metrics);
        
        // 记录性能数据
        await logPerformanceData(metrics);
        
        // 如果有警报，生成报告
        if (alerts.length > 0) {
          await generatePerformanceReport(metrics, alerts);
        }
        
        await new Promise(resolve => setTimeout(resolve, interval));
      }
    } else {
      // 单次执行模式
      const metrics = await collectMetrics();
      const alerts = analyzeMetrics(metrics);
      
      if (collectOnly) {
        console.log(JSON.stringify(metrics, null, 2));
      } else if (generateReport) {
        const reportFile = await generatePerformanceReport(metrics, alerts);
        printMessage(colors.green, `报告已生成: ${reportFile}`);
      } else {
        // 默认显示摘要
        printMessage(colors.cyan, '性能监控摘要');
        printMessage(colors.cyan, '================');
        
        console.log(`CPU使用率: ${metrics.system.cpu.toFixed(1)}%`);
        console.log(`内存使用率: ${metrics.system.memory.usagePercent}%`);
        console.log(`磁盘使用率: ${metrics.system.disk.usagePercent}%`);
        console.log(`应用状态: ${metrics.application.status}`);
        console.log(`数据库连接: ${metrics.database.connections}/${metrics.database.maxConnections}`);
        
        if (alerts.length > 0) {
          console.log();
          printMessage(colors.yellow, `发现 ${alerts.length} 个警报:`);
          alerts.forEach(alert => {
            const color = alert.level === 'CRITICAL' ? colors.red : colors.yellow;
            printMessage(color, `  [${alert.level}] ${alert.message}`);
          });
        } else {
          console.log();
          printMessage(colors.green, '✓ 系统运行正常');
        }
      }
    }
  } catch (error) {
    console.error('执行失败:', error.message);
    process.exit(1);
  }
}

// 错误处理
process.on('unhandledRejection', (error) => {
  console.error('未处理的错误:', error.message);
  process.exit(1);
});

// 优雅退出
process.on('SIGINT', () => {
  printMessage(colors.blue, '\n监控已停止');
  process.exit(0);
});

// 运行主函数
if (require.main === module) {
  main().catch(error => {
    console.error('启动失败:', error.message);
    process.exit(1);
  });
}

module.exports = {
  collectMetrics,
  analyzeMetrics,
  generatePerformanceReport
};